// -----------------------------
// Author: 		Dhaenens Gert 
// Creation: 	2/19/2014 9:09:03 AM				
// -----------------------------

#ifndef _IRenderDevice_h
#define _IRenderDevice_h

#include "DxCommon.h"

namespace DxLib
{

	class IAdapter;
	class IRenderTarget;
	class IDepthStencil;

	class IInputLayout;
	class ISamplerState;
	class IRasterizerState;
	class IBlendState;
	class IDepthStencilState;
	
	class IBuffer;

	class IVertexShader;
	class IPixelShader;
	class IGeometryShader;
	class IHullShader;
	class IDomainShader;
	class IComputeShader;

	class DXLIB IRenderDevice
	{
	public:
		// Create the Interface
		static IRenderDevice*	Create(HWND hOutputWindow, UInt32 uWidth, UInt32 uHeight, Bool bFullscreen, Bool bDebug, Bool bUseD2D = true, Bool bBestAdapter = false);
		// Release the Interface
		virtual void			Release() = 0;

		// Switch the Fullscreen State
		virtual Bool			SetFullscreenState(Bool bFullscreen) = 0;
		// Resize the Swapchain
		virtual Bool			Resize(UInt32 uWidth, UInt32 uHeight) = 0;

		// Reset the Shaders
		virtual void			ResetShaders() = 0;
		// Reset the Device
		virtual void			Reset() = 0;

		// Set the Topology
		virtual void			SetTopology(Topology eTopology) = 0;

		// Set the Depth Stencil State
		virtual void			SetDepthStencilState(IDepthStencilState* lpState) = 0;

		// Set an individual Render Target
		virtual void			SetRenderTarget(IRenderTarget* lpRenderTarget, IDepthStencil* lpDepthStencil) = 0;
		// Set multiple Render Targets
		virtual void			SetRenderTargets(IRenderTarget* arrTargets[], UInt32 uTargetCount, IDepthStencil* lpDepthStencil) = 0;

		// Set the Input Layout
		virtual void			SetInputLayout(IInputLayout* lpLayout) = 0;

		// Set the Rasterizer State
		virtual void			SetRasterizerState(IRasterizerState* lpState) = 0;

		// Set the Blend State
		virtual void			SetBlendState(IBlendState* lpState, const Float* lpBlendFactors = nullptr, UInt32 blendMask = 0xFFFFFFFF) = 0;

		// Set an Index Buffer
		virtual void			SetIndexBuffer(IBuffer* lpBuffer) = 0;
		// Set a Vertex Buffer
		virtual void			SetVertexBuffer(UInt32 uSlot, IBuffer* lpBuffer) = 0;

		// Set the Vertex Shader
		virtual void			SetVertexShader(IVertexShader* lpShader) = 0;
		// Set the Pixel Shader
		virtual void			SetPixelShader(IPixelShader* lpShader) = 0;
		// Set the Geometry Shader
		virtual void			SetGeometryShader(IGeometryShader* lpShader) = 0;
		// Set the Hull Shader
		virtual void			SetHullShader(IHullShader* lpShader) = 0;
		// Set the Domain Shader
		virtual void			SetDomainShader(IDomainShader* lpShader) = 0;
		// Set the Compute Shader
		virtual void			SetComputeShader(IComputeShader* lpShader) = 0;

		// Set the Viewport
		virtual void			SetViewport(Float topLeftX, Float topLeftY, Float width, Float height, Float minDepth, Float maxDepth) = 0;

		// Draw using a Vertex Buffer
		virtual void			Draw(UInt32 uVertexCount, UInt32 uStartIndex = 0) = 0;
		// Draw using a Vertex & Index Buffer
		virtual void			DrawIndexed(UInt32 uIndexCount, UInt32 uBaseIndex = 0, UInt32 uBaseVertex = 0) = 0;

		// Dispatch a Compute Shader
		virtual void			Dispatch(UInt32 uThreadCountX, UInt32 uThreadCountY, UInt32 uThreadCountZ) = 0;

		// Present the Output Target
		virtual Bool			Present(Bool bVSync) = 0;

		// Get the Current Multi-Sample Count
		virtual UInt32			GetSampleCount() const = 0;
		// Get the Current Multi-Sample Quality
		virtual UInt32			GetSampleQuality() const = 0;

		// Get the Fullscreen State
		virtual Bool			GetFullscreenState() const = 0;

		// Get the Adapter used
		virtual IAdapter*		GetAdapter() const = 0;

	};

}

#endif